package com.example.stock.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.stock.dto.ratio.RatioReq;
import com.example.stock.dto.ratio.RatioRsp;
import com.example.stock.entity.ratio.RatioEnity;
import com.example.stock.mapper.RatioMapper;
import com.example.stock.service.RatioService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.*;

/**
 * @author ：Zhengyu Wang
 * @date ：Created in 2023/4/12 18:58
 * @description：
 * @modified By：
 * @version: $
 */
@Service
public class RatioServiceImpl extends ServiceImpl<RatioMapper, RatioEnity> implements RatioService {

    @Autowired
    private RatioMapper ratioMapper;

    @Override
    public List<RatioRsp> getStockInfo(RatioReq ratioReq) {
        String stockId = ratioReq.getStockId();
        String setNow = ratioReq.getSetNow();
        int mb = ratioReq.getMb();
        int ms = ratioReq.getMs();
        int lb = ratioReq.getLb();
        int ls = ratioReq.getLs();

        // TREE 万一数据库不是最新，不到当日日期，此时我们查询一次数据库获取其第一条数据和最后一条数据时间，来判定是否存在多年前数据
        // 不过当前如果传入一个设置当前时间的值,那么我们就不需要进行下面的截至时间判断

        // 获取去掉最后N天的数据（即处理回退多少天的数据集）
        QueryWrapper<RatioReq> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("stock_name", stockId);
        queryWrapper.le("sd.day_time", setNow);
        queryWrapper.orderByDesc("sd.day_time");
        queryWrapper.last("limit " + (lb + ls));
        // 获取结果集列表，剩下所有数据在这里处理
        List<RatioEnity> parameters = ratioMapper.getParameters(queryWrapper);
        RatioRsp ratioRsp = new RatioRsp();
        List<RatioRsp> rsp = new ArrayList<>();
        if (parameters.size() == 0) {
            ratioRsp.setScore(-1);
            rsp.add(ratioRsp);
            return rsp;
        } else if (parameters.size() <= 260) {
            ratioRsp.setScore(1);
            rsp.add(ratioRsp);
            return rsp;
        }

        // 如果数据集结果大于当前需要的条数
        List<RatioEnity> longTermList;
        List<RatioEnity> middleTermList;
        if (parameters.size() >= ls + lb) {
            longTermList = parameters.subList(lb, ls);
            middleTermList = parameters.subList(mb, ms);
        } else if (parameters.size() > ms) {
            // 如果结果集条数大于中期所需，直接取第N条往后的数据
            longTermList = parameters.subList(lb, parameters.size());
            middleTermList = parameters.subList(mb, ms);
        } else {
            longTermList = parameters.subList(lb, parameters.size());
            middleTermList = parameters.subList(mb, parameters.size());
        }
        // 获取最大最小值
        RatioEnity maxLongRealPrice =
                longTermList.stream().max(Comparator.comparing(RatioEnity::getRealPrice)).orElse(null);
        RatioEnity minLongRealPrice =
                longTermList.stream().min(Comparator.comparing(RatioEnity::getRealPrice)).orElse(null);
        RatioEnity maxMiddleRealPrice =
                middleTermList.stream().max(Comparator.comparing(RatioEnity::getRealPrice)).orElse(null);
        RatioEnity minMiddleRealPrice =
                middleTermList.stream().min(Comparator.comparing(RatioEnity::getRealPrice)).orElse(null);

        // 获取四个必须值
//        RatioRsp ratioRsp = new RatioRsp();
        // 长期最高价
        assert maxLongRealPrice != null;
        double longMax = maxLongRealPrice.getRealPrice();
        // 中期最高价
        double longMin = minLongRealPrice.getRealPrice();
        // 中期最高价
        assert maxMiddleRealPrice != null;
        double middleMax = maxMiddleRealPrice.getRealPrice();
        // 中期最高价
        double middleMin = minMiddleRealPrice.getRealPrice();
        ratioRsp.setMaxLongRealPrice(longMax);
        ratioRsp.setMinLongRealPrice(longMin);
        ratioRsp.setMaxMiddleRealPrice(middleMax);
        ratioRsp.setMinMiddleRealPrice(middleMin);
        // 获取当天价格
        double nowRealPrice = parameters.get(0).getRealPrice();
        ratioRsp.setRealPrice(nowRealPrice);

        // 获取五个必须参数后进行处理
        // 长/短期盈亏比1.2 .潜在赢值/ 潜在亏值
        double longTermBackProfit1 = longMax - nowRealPrice;
        double longTermBackLoss1 = nowRealPrice - longMin;
        double longTermBackProfit2 = longMax * 2 - nowRealPrice;
        double longTermBackLoss2 = nowRealPrice - longMax;
        double middleTermBackProfit1 = middleMax - nowRealPrice;
        double middleTermBackLoss1 = nowRealPrice - middleMin;
        double middleTermBackProfit2 = middleMax * 2 - nowRealPrice;
        double middleTermBackLoss2 = nowRealPrice - middleMax;

//        长期盈亏比1,2 中期盈亏比1,2

        double longTermRatio1 =
                longTermBackLoss1 > 0 ?
                        (longTermBackProfit1 - longTermBackLoss1) /
                                (longTermBackProfit1 + longTermBackLoss1) / 2 : 0;
        double longTermRatio2 =
                longTermBackLoss2 > 0 ?
                        (longTermBackProfit2 - longTermBackLoss2) /
                                (longTermBackProfit2 + longTermBackLoss2) / 2 : 0;
        double middleTermRatio1 =
                middleTermBackLoss1 > 0 ?
                        (middleTermBackProfit1 - middleTermBackLoss1)
                                / (middleTermBackProfit1 + middleTermBackLoss1) / 2 : 0;
        double middleTermRatio2 =
                middleTermBackLoss2 > 0 ?
                        (middleTermBackProfit2 - middleTermBackLoss2)
                                / (middleTermBackProfit2 + middleTermBackLoss2) / 2 : 0;

        double longTermRatio1Fix = longTermRatio1 > 0 ? longTermRatio1 : 0;
        double longTermRatio2Fix = longTermRatio2 > 0 ? longTermRatio2 : 0;
        double middleTermRatio1Fix = middleTermRatio1 > 0 ? middleTermRatio1 : 0;
        double middleTermRatio2Fix = middleTermRatio2 > 0 ? middleTermRatio2 : 0;
        double longTermRatioResult = nowRealPrice < longMax ? longTermRatio1Fix : longTermRatio2Fix;
        double middleTermRatioResult = nowRealPrice < middleMax ? middleTermRatio1Fix : middleTermRatio2Fix;
        double longTermRatioResultTotal = (longTermRatioResult + middleTermRatioResult) * 100;
        double ratioResult = longTermRatioResultTotal > 0 ? longTermRatioResultTotal : 1;

        ratioRsp.setScore(ratioResult);
        // 封装响应实体
        rsp.add(ratioRsp);
        return rsp;
    }
}
